home *** CD-ROM | disk | FTP | other *** search
- /********************************************************
- LZSS法による圧縮
-
- 88.8.15 Original 奥村晴彦(Turbo-C MS-DOS)
- 89.2.27 OS9/6809 MW-C Convert Nanno-NET Ken
- 89.2.27 Bug Fix ? Apend insnode(r,len) "len" by ken
- 90.1.27 Modefal By Ken
- *********************************************************/
- #include <stdio.h>
- #include <stdlib.h>
-
- #define TRUE 1
- #define FALSE 0
- #define ERR (-1)
-
- #define unlink remove
-
- #define N 2048 /* バッファサイズ Max 4096 */
- #define F 18 /* 先読みバッファサイズ Max 18 */
- #define NIL N /* 木の末端 */
-
- char *mak_work(char *file);
-
- unsigned short int t_crc=0;
-
- static unsigned int mask;
- static char *bas,*ptr;
- static char dmy_buf[18];
- static int now,new,len;
- static int status,adr;
- static int pos,mat_len;
- static char *md_ptr;
-
- static char text_buf[N+F-1];
- static int lson[N+1];
- static int rson[N+257];
- static int dad[N+1];
-
- static unsigned short int crctbl[] = {
- 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
- 0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
- 0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
- 0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
- 0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
- 0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
- 0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
- 0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
- 0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
- 0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
- 0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
- 0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
- 0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
- 0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
- 0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
- 0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
- 0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
- 0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
- 0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
- 0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
- 0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
- 0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
- 0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
- 0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
- 0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
- 0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
- 0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
- 0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
- 0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
- 0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
- 0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
- 0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 };
-
- void calcrc(unsigned char ch)
- {
- t_crc = (t_crc >> 8 ^ crctbl[(t_crc ^ ch) & 0xff]);
- }
-
- void insnode(r,len)
- int r,len;
- {
- int i,cmp;
- unsigned char *key;
- register int p;
-
- cmp = 1;
- key = (unsigned char *)&text_buf[r];
- p = N + 1 + key[0];
- rson[r] = lson[r] = NIL; mat_len = 0;
- for ( ; ; ) {
- if ( cmp >= 0 ) {
- if ( rson[p] != NIL )
- p = rson[p];
- else {
- rson[p] = r; dad[r] = p;
- return;
- }
- } else {
- if ( lson[p] != NIL )
- p = lson[p];
- else {
- lson[p] = r; dad[r] = p;
- return;
- }
- }
- for ( i = 1 ; i < len ; i++ ) {
- if ( (cmp = key[i] - (unsigned char)text_buf[p + i]) != 0 )
- break;
- }
- if ( i > mat_len ) {
- pos = p;
- if ( (mat_len = i) >= len )
- break;
- }
- }
- dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
- dad[lson[p]] = r; dad[rson[p]] = r;
- if ( rson[dad[p]] == p )
- rson[dad[p]] = r;
- else
- lson[dad[p]] = r;
- dad[p] = NIL;
- }
- void delnode(p)
- int p;
- {
- int q;
- register int dad_p;
-
- if ( (dad_p = dad[p]) == NIL )
- return;
- if ( rson[p] == NIL ) {
- if ( rson[dad_p] == p )
- rson[dad_p] = lson[p];
- else
- lson[dad_p] = lson[p];
- dad[lson[p]] = dad_p;
- } else if ( lson[p] == NIL ) {
- if ( rson[dad_p] == p )
- rson[dad_p] = rson[p];
- else
- lson[dad_p] = rson[p];
- dad[rson[p]] = dad_p;
- } else {
- q = lson[p];
- if ( rson[q] != NIL ) {
- do {
- q = rson[q];
- } while ( rson[q] != NIL );
- rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
- lson[q] = lson[p]; dad[lson[p]] = q;
- rson[q] = rson[p]; dad[rson[p]] = q;
- } else {
- rson[q] = rson[p]; dad[rson[p]] = q;
- }
- dad[q] = dad_p;
- if ( rson[dad_p] == p )
- rson[dad_p] = q;
- else
- lson[dad_p] = q;
- }
- dad[p] = NIL;
- }
- void Enc_init(fp)
- FILE *fp;
- {
- int i,c;
-
- for ( i = N + 1 ; i <= (N + 256) ; i++ )
- rson[i] = NIL;
- for ( i = 0 ; i < N ; i++ )
- dad[i] = NIL;
- for ( i = 0 ; i < (N - F) ; i++ )
- text_buf[i] = ' ';
-
- bas = dmy_buf;
- ptr = dmy_buf + 1;
- dmy_buf[0] = 0;
- mask = 1;
- now = N- F;
- new = 0;
- t_crc = 0;
-
- for ( len = 0 ; len < F && (c = getc(fp)) != EOF ; len++ ) {
- text_buf[now + len] = c;
- calcrc(c);
- }
- for ( i = 1 ; i <= F ; i++ )
- insnode(now - i,len);
- insnode(now,len);
- }
- int Enc_char(fp)
- FILE *fp;
- {
- int i,n,c;
-
- for ( ; ; ) {
- if ( mask >= 0x100 ) {
- if ( bas < ptr )
- return *(bas++) & 0xFF;
- dmy_buf[0] = 0;
- mask = 1;
- bas = dmy_buf;
- ptr = dmy_buf + 1;
- }
- if ( len <= 0 )
- return EOF;
-
- if ( mat_len <= 2 ) {
- mat_len = 1;
- dmy_buf[0] |= mask;
- *(ptr++) = text_buf[now];
- } else {
- if ( mat_len > len ) mat_len = len;
- *(ptr++) = pos;
- *(ptr++) = (((pos >> 4) & 0xf0) | (mat_len -3));
- }
-
- n = mat_len;
- for ( i = 0 ; i < n &&
- (c = getc(fp)) != EOF ; i++ ) {
- delnode(new);
- text_buf[new] = c;
- if ( new < (F - 1) )
- text_buf[new + N] = c;
- new = (new + 1) & (N - 1);
- now = (now + 1) & (N - 1);
- insnode(now,len);
- calcrc(c);
- }
- while ( i++ < n ) {
- delnode(new);
- new = (new + 1) & (N - 1);
- now = (now + 1) & (N - 1);
- if ( --len > 0 )
- insnode(now,len);
- }
-
- if ( len <= 0 )
- mask = 0x100;
- else
- mask <<= 1;
- }
- }
-
- #define D_Get_Mask 0
- #define D_Get_Char 1
- #define D_Get_HiAd 2
-
- void Dec_init()
- {
- int i;
-
- for ( i = 0 ; i < (N - F) ; i++ )
- text_buf[i] = ' ';
- now = N - F;
- mask = 0;
- status = D_Get_Char;
- t_crc = 0;
- }
- void Dec_char(ch,fp)
- unsigned int ch;
- FILE *fp;
- {
- int n;
-
- ch &= 0xFF;
- switch(status) {
- case D_Get_Char:
- if ( (mask & 0x100) == 0 ) {
- mask = 0xFF00 | ch;
- } else {
- if ( mask & 1 ) {
- putc(ch,fp);
- text_buf[now++] = ch;
- now &= (N - 1);
- calcrc(ch);
- } else {
- adr = ch;
- status = D_Get_HiAd;
- }
- mask >>= 1;
- }
- break;
- case D_Get_HiAd:
- adr |= ((ch & 0xf0) << 4);
- n = (ch & 0x0f) + 3;
- while ( n-- > 0 ) {
- ch = text_buf[adr++];
- adr &= (N - 1);
- putc(ch,fp);
- text_buf[now++] = ch;
- now &= (N - 1);
- calcrc(ch);
- }
- status = D_Get_Char;
- break;
- }
- }
-
- void MDec_char(int ch)
- {
- int n;
-
- ch &= 0xFF;
- switch(status) {
- case D_Get_Char:
- if ( (mask & 0x100) == 0 ) {
- mask = 0xFF00 | ch;
- } else {
- if ( mask & 1 ) {
- *(md_ptr++) = ch;
- text_buf[now++] = ch;
- now &= (N - 1);
- } else {
- adr = ch;
- status = D_Get_HiAd;
- }
- mask >>= 1;
- }
- break;
- case D_Get_HiAd:
- adr |= ((ch & 0xf0) << 4);
- n = (ch & 0x0f) + 3;
- while ( n-- > 0 ) {
- ch = text_buf[adr++];
- adr &= (N - 1);
- *(md_ptr++) = ch;
- text_buf[now++] = ch;
- now &= (N - 1);
- }
- status = D_Get_Char;
- break;
- }
- }
- char *MEM_lzss(FILE *fp)
- {
- int n,ch;
- char *p;
- char tmp[8];
-
- fread(tmp,1,5,fp);
- if ( strncmp(tmp,"LZSS\x1A",5) != 0 ) {
- rewind(fp);
- return NULL;
- }
-
- for ( n = 0 ; n < (N - F) ; n++ )
- text_buf[n] = ' ';
- now = N - F;
- mask = 0;
- status = D_Get_Char;
-
- fread(&n,sizeof(int),1,fp);
- if ( (p = md_ptr = malloc(n)) == NULL )
- return NULL;
-
- while ( (ch = getc(fp)) != EOF && md_ptr < (p + n) )
- MDec_char(ch);
-
- return p;
- }
- int COMP_lzss(char *file)
- {
- FILE *ifp,*ofp;
- int ch,fg,sw=FALSE;
- long fsz;
- char *work;
- char tmp[8];
-
- if ( (ifp = fopen(file,"rb")) == NULL )
- return ERR;
-
- work = mak_work(file);
- if ( (ofp = fopen(work,"wb")) == NULL ) {
- fclose(ifp);
- return ERR;
- }
-
- fread(tmp,1,5,ifp);
- if ( strncmp(tmp,"LZSS\x1A",5) != 0 )
- sw = TRUE;
-
- if ( sw == FALSE ) {
- fseek(ifp,0L,SEEK_END);
- fsz = ftell(ifp);
- rewind(ifp);
-
- fwrite("LZSS\x1A",1,5,ofp);
- fwrite(&fsz,sizeof(long),1,ofp);
-
- Enc_init(ifp);
- while ( (ch = Enc_char(ifp)) != EOF )
- putc(ch,ofp);
-
- } else {
- fread(&fsz,sizeof(long),1,ifp);
-
- Dec_init();
- while ( (ch = getc(ifp)) != EOF )
- Dec_char(ch,ofp);
- }
-
- fg = (ferror(ifp) || ferror(ofp)) ? ERR:FALSE;
-
- fclose(ifp);
- fclose(ofp);
-
- if ( fg != FALSE )
- unlink(work);
- else {
- unlink(file);
- rename(work,file);
- }
-
- return fg;
- }